/*
 *  Copyright 2010-2011, Social Music Discovery project
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of Social Music Discovery project nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *  DISCLAIMED. IN NO EVENT SHALL SOCIAL MUSIC DISCOVERY PROJECT BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.socialmusicdiscovery.server.business.repository.core;

import com.google.inject.Inject;
import org.socialmusicdiscovery.server.business.model.core.Artist;
import org.socialmusicdiscovery.server.business.model.core.ArtistEntity;
import org.socialmusicdiscovery.server.business.model.core.PersonEntity;
import org.socialmusicdiscovery.server.business.model.core.RecordingEntity;
import org.socialmusicdiscovery.server.business.repository.AbstractJPASMDIdentityRepository;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.Collection;

public class JPAPersonRepository extends AbstractJPASMDIdentityRepository<PersonEntity> implements PersonRepository {
    ArtistRepository artistRepository;
    RecordingRepository recordingRepository;

    @Inject
    public JPAPersonRepository(EntityManager em, ArtistRepository artistRepository, RecordingRepository recordingRepository) {
        super(em);
        this.artistRepository = artistRepository;
        this.recordingRepository = recordingRepository;
    }

    public Collection<PersonEntity> findByName(String name) {
        return findByNameWithRelations(name, null, null);
    }

    public Collection<PersonEntity> findByNameWithRelations(String name, Collection<String> mandatoryRelations, Collection<String> optionalRelations) {
        Query query = entityManager.createQuery(queryStringFor("e",mandatoryRelations, optionalRelations)+" where lower(e.name)=:name");
        query.setParameter("name",name.toLowerCase());
        return query.getResultList();
    }

    public Collection<PersonEntity> findByPartialNameWithRelations(String name, Collection<String> mandatoryRelations, Collection<String> optionalRelations) {
        Query query = entityManager.createQuery(queryStringFor("e",mandatoryRelations, optionalRelations)+" where lower(e.name) like :name");
        query.setParameter("name","%"+name.toLowerCase()+"%");
        return query.getResultList();
    }

    @Override
    public void create(PersonEntity entity) {
        if(entity.getSortAs()==null) {
            entity.setSortAsAutomatically();
        }
        super.create(entity);
    }

    @Override
    public PersonEntity merge(PersonEntity entity) {
        if(entity.getSortAs()==null) {
            entity.setSortAsAutomatically();
        }
        return super.merge(entity);
    }

    public void remove(PersonEntity entity) {
        Collection<RecordingEntity> recordings = recordingRepository.findBySearchRelation(entity);
        Collection<ArtistEntity> artists = artistRepository.findByPersonWithRelations(entity.getId(), null, null);
        for (Artist artist : artists) {
            artist.setPerson(null);
        }
        entity.getSearchRelations().clear();
        super.remove(entity);
        for (RecordingEntity recording : recordings) {
            recordingRepository.refresh(recording);
        }
    }

    public void refresh(PersonEntity entity) {
        Collection<ArtistEntity> artists = artistRepository.findByPersonWithRelations(entity.getId(), null, null);
        for (ArtistEntity artist : artists) {
            artistRepository.refresh(artist);
        }
    }
}
